package cn.k7g.alloy.ioc.conversion;

import cn.k7g.alloy.annotation.AlloyContent;
import cn.k7g.alloy.exception.AlloyContentDecodeException;
import cn.k7g.alloy.exception.AlloyMessageException;
import cn.k7g.alloy.expose.AlloyContentHandler;
import cn.k7g.alloy.model.AlloyContentHold;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.format.WebConversionService;
import org.springframework.context.ApplicationContext;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;

/**
 * 重写convert支持query 参数
 * @author victor-wu
 * @date 2021/9/27 下午1:10
 */
@Component
public class AlloyContentConverter implements GenericConverter {

    @Autowired
    ApplicationContext context;

    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        Set<ConvertiblePair> objects = new HashSet<>();
        objects.add(new ConvertiblePair(String.class, AlloyContentHold.class));
        return objects;
    }

    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        try {
            WebConversionService conversionService = context.getBean(WebConversionService.class);
            AlloyContent alloyContent = targetType.getAnnotation(AlloyContent.class);
            if (alloyContent != null) {
                AlloyContentHandler handler = AlloyContentHandler.newInstance(context, alloyContent);
                String val = handler.decodeObject(source.toString(), String.class);
                Annotation[] objects = new Annotation[targetType.getAnnotations().length - 1];
                int i = 0;
                for (Annotation annotation : targetType.getAnnotations()) {
                    if (!(annotation instanceof AlloyContent)) {
                        objects[i++] = annotation;
                    }
                }
                targetType = new TypeDescriptor(targetType.getResolvableType(), targetType.getType(), objects);
                return conversionService.convert(val, sourceType, targetType);
            } else {
                return conversionService.convert(source, sourceType, targetType);
            }
        } catch (AlloyContentDecodeException e) {
            throw new AlloyMessageException(e);
        }
    }

}
